package org.molamil.acto.core.loggers {
	import flash.errors.IllegalOperationError;	
	
	/**
	 * Basic pseudo-logger mock-up.
	 * 
	 * @author Jorge Hernandez
	 */
	public class Logger {
		
		
		// CONSTANTS
	
		/**
		 * Name for the default logger, used with <code>getLogger()</code> 
		 * with no params.
		 */
		public static const DEFAULT_LOGGER_NAME:String = "APP";
		
		/**
		 * Off level - no logging.
		 */
		public static const LEVEL_OFF:Number = 0;
		
		/**
		 * Severe level.
		 */
		public static const LEVEL_SEVERE:Number = 1;
		
		/**
		 * Warning level. 
		 */
		public static const LEVEL_WARNING:Number = 2;
		
		/**
		 * Info level. 
		 */
		public static const LEVEL_INFO:Number = 3;
		
		/**
		 * Debug level. 
		 */
		public static const LEVEL_DEBUG:Number = 4;
		
		private static const LEVEL_LABELS:Array = ["", "SEVERE", "WARNING", "INFO", "DEBUG"];
		
		
		// PROPERTIES
		
		/**
		 * Current log level - 1 to 4, DEBUG to SEVERE.
		 */
		public static var level:Number = LEVEL_WARNING;
		
		private static var loggers:Object = new Object();
		
		private var name:String;
		
		
		// CONSTRUCTOR
		
		public function Logger(lock:Class) {
			if (lock != SingletonLock)
				throw new IllegalOperationError("Logger cannot be instantiated, " +
					"use Logger.getLogger()");
		}
		
		
		// PUBLIC METHODS
		
		/**
		 * Singleton method to get a <code>Logger</code>.
		 * 
		 * @return  Logger instance.
		 */
		public static function getLogger(name:String):Logger {
			
			var instance:Logger;
			
			// Create a default Logger if it's not there.
		    if (loggers[DEFAULT_LOGGER_NAME] == null) {
				loggers[DEFAULT_LOGGER_NAME] = new Logger(SingletonLock);
				loggers[DEFAULT_LOGGER_NAME].name = DEFAULT_LOGGER_NAME;
			}
			
			// If there's no name, we return the default Logger.
			if (name == null) {
				instance = loggers[DEFAULT_LOGGER_NAME];
			} else {
				loggers[name] = new Logger(SingletonLock);
				loggers[name].name = name;
				instance = loggers[name];
			}
			
			return instance;
			
		}
		
		public function debug(message:String):void {
			log(LEVEL_DEBUG, message);
		}
		
		public function info(message:String):void {
			log(LEVEL_INFO, message);
		}
		
		public function severe(message:String):void {
			log(LEVEL_SEVERE, message);
		}
		
		public function warning(message:String):void {
			log(LEVEL_WARNING, message);
		}
		
		private function log(level:Number, message:String):void {
			if (Logger.level >= level) {
				var d:Date = new Date();
				var ds:String = d.getFullYear() 
					+ "-" + paddLeft("" + (d.getMonth() + 1), 2, "0")
					+ "-" + paddLeft("" + d.getDate(), 2, "0")
					+ " " + paddLeft("" + d.getHours(), 2, "0")
					+ ":" + paddLeft("" + d.getMinutes(), 2, "0")
					+ ":" + paddLeft("" + d.getSeconds(), 2, "0")
					+ ":" + paddLeft("" + d.getMilliseconds(), 2, "0");
				var s:String = paddRight(ds, 15)
					+ " - " + paddRight(LEVEL_LABELS[level], 7)
					+ " - " + paddRight(name, 24)
					+ " - " + message;
				trace(s);
			}
		}
		
		private function paddRight(s:String, l:Number, c:String = null):String {
			if (c == null)
				c = " ";
			while (s.length < l)
				s += c;
			return s;
		}
		
		private function paddLeft(s:String, l:Number, c:String = null):String {
			if (c == null)
				c = " ";
			while (s.length < l)
				s = c + s;
			return s;
		}
		
	}
}

class SingletonLock {}
